#include "ba.h"

#define BA_MODBUS_CMD_NUM                    43

CBA::CBA(QObject *pWgt, CModbusFactory* pModbusFactory, CBattStack* pStackMaster)
	: QThread(pWgt)
{
	// init some variables
	m_pModbusFactory = pModbusFactory;
	m_bPrintBAMsg = false;

	m_bAcquSglDataEnable = false;
	m_bAcquComInputRegEnable = false;
	for (int i = 0; i < 100; ++i)
	{
		m_usComInputRegVal[i] = 0;
	}
	m_iBAIndex = -1;

	m_strIP = "127.0.0.1";
	m_usPort = 502;
	m_pTcpClient = 0;
	m_bTcpConnected = false;

	m_iTryConnectBANum = 0; //尝试连接BA计数
	m_bBAConnected = true;

	m_pDataBuf = new char[SNED_BUFFER_LENGHT];
	m_iHasReadBytesNum = 0;

	m_iCellNum = -1; //采集单体数据时, 控制帧数 提高速度
	m_iTempNum = -1;

	m_pSemaphore = new QSemaphore;
	m_uaAddrBg = 0;
	m_pTranDataBuf = 0;
	m_iTranDataLen = 0;

	m_pLstBatt = new QList<CBattBank*>;
	m_pLstSlaveParam = new QList<SAlarmParam*>;
	m_pBattStack = new CBattStack;
	memset(m_pBattStack, 0, sizeof(CBattStack));
	m_pBattStack->usStackState = 0xbbbb; //默认为正常
    // m_pBattStack->usBranState1 = 0xbbbb; //默认为正常
    // m_pBattStack->usBranState2 = 0xbbbb; //默认为正常
    // m_pBattStack->usBranState3 = 0xbbbb; //默认为正常
    // m_pBattStack->usBranState4 = 0xbbbb; //默认为正常
	m_pBattStackMaster = pStackMaster;

	m_iLinkageStrategy = 0;
	
	QObject::connect(this, SIGNAL(addLog(int, const QString&)), pWgt, SLOT(addLog(int, const QString&)));
	QObject::connect(this, SIGNAL(notifyBAStateChanged(const QString&, bool)), pWgt, SLOT(notifyBAStateChanged(const QString&, bool)));
}

CBA::~CBA()
{
	/*if (m_pTcpClient)
	{
		delete m_pTcpClient;
		m_pTcpClient = 0;
	}*/

	if (m_pDataBuf)
	{
		delete []m_pDataBuf;
		m_pDataBuf = 0;
	}

	if (m_pLstBatt)
	{
		while (!m_pLstBatt->isEmpty())
		{
			delete m_pLstBatt->takeFirst();
		}
		
		delete m_pLstBatt;
		m_pLstBatt = 0;
	}

	if (m_pLstSlaveParam)
	{
		while (!m_pLstSlaveParam->isEmpty())
		{
			delete m_pLstSlaveParam->takeFirst();
		}

		delete m_pLstSlaveParam;
		m_pLstSlaveParam = 0;
	}

	if (m_pBattStack)
	{
		delete m_pBattStack;
		m_pBattStack = 0;
	}

	if (m_pSemaphore)
	{
		delete m_pSemaphore;
		m_pSemaphore = 0;
	}
}

void CBA::disconnected()
{
	m_bTcpConnected = false;
}

void CBA::run()
{
	// Client
	m_pTcpClient = new QTcpSocket;//(this);
	QObject::connect(m_pTcpClient, SIGNAL(disconnected()), this, SLOT(disconnected()));

	// some variables
	CBattBank* pBattBank = 0;
	int iIndexStep = 0;
	int iRetVal = -1;
	int iErrNum = 0;

	while (true)
	{
		msleep(100);

		if (!m_bTcpConnected)//每次通信前检查连接状态
		{
			// connect to server
			emit addLog(RUN_LOG_OK, QString("Try to connnect BA(%1:%2)...").arg(m_strIP).arg(m_usPort));

			m_pTcpClient->connectToHost(m_strIP, m_usPort);

			if (!m_pTcpClient->waitForConnected(2000)) 
			{
				++m_iTryConnectBANum;
				if (m_iTryConnectBANum > 40)
				{
					if (m_iTryConnectBANum < 50)//最多尝试50次，超过后停止打印日志，
					{
						emit notifyBAStateChanged(QString("%1:%2").arg(m_strIP).arg(m_usPort), false);
						emit addLog(RUN_LOG_FAILED, "BA State change to DISConnected.");
					}

					m_bBAConnected = false;
					m_iTryConnectBANum = 51;
				}

				emit addLog(RUN_LOG_FAILED, QString("Try to connnect BA(%1:%2) FAILED.(Err Code:%3 Err Info:%4)").arg(m_strIP).arg(m_usPort).arg(m_pTcpClient->error()).arg(m_pTcpClient->errorString()));
			}
			else
			{
				emit addLog(RUN_LOG_OK, QString("Connnect to BA(%1:%2) OK.").arg(m_strIP).arg(m_usPort));
				if (!m_bBAConnected)
				{
					emit notifyBAStateChanged(QString("%1:%2").arg(m_strIP).arg(m_usPort), true);
				}

				m_bTcpConnected = true;

				m_iTryConnectBANum = 0; //尝试连接BA计数
				m_bBAConnected = true;
			}
		}
		else
		{
			// 是否采集通用输入寄存器  iIndexStep = 200
			if (m_bAcquComInputRegEnable)
			{
				iIndexStep = 200;

				iRetVal = m_pModbusFactory->prepareDatagram(iIndexStep, m_pDataBuf, 100/*Modbus Addr*/); // >= 0 OK  -1 准备失败  -2 最后了

				if (iRetVal >= 0)
				{
					printSendInfo(iIndexStep, m_pDataBuf, iRetVal);

					if (iRetVal != m_pTcpClient->write(m_pDataBuf, iRetVal))
					{
						++iErrNum;
						emit addLog(RUN_LOG_FAILED, QString("Write data(%1) to BA(%2:%3) FAILED.").arg(getMsgFromIndexStep(iIndexStep)).arg(m_strIP).arg(m_usPort));
					}
					else
					{
						m_pTcpClient->flush();

						// receive data
						if (!m_pTcpClient->waitForReadyRead(1500)) //timeout
						{
							++iErrNum;
							emit addLog(RUN_LOG_FAILED, QString("Read data(%1) to BA(%2:%3) Timeout.").arg(getMsgFromIndexStep(iIndexStep)).arg(m_strIP).arg(m_usPort));
						}
						else
						{
							memset(m_pDataBuf, 0, SNED_BUFFER_LENGHT);
							iRetVal = m_pTcpClient->read(m_pDataBuf, SNED_BUFFER_LENGHT);

							if (iRetVal >= 0) //read OK
							{
								printReceInfo(iIndexStep, m_pDataBuf, iRetVal);

								iRetVal = m_pModbusFactory->analyComInputRegDatagram(m_pDataBuf, iRetVal, m_usComInputRegVal);

								if (0 == iRetVal)
								{
									emit addLog(RUN_LOG_OK, QString("Analy Datagram:%1 OK.").arg(getMsgFromIndexStep(iIndexStep)));
								}
								else
								{
									emit addLog(RUN_LOG_FAILED, QString("Analy Datagram:%1 FAILED. Err Code:%2.").arg(getMsgFromIndexStep(iIndexStep)).arg(iRetVal));
								}
							}

							iErrNum = 0; // 分析正确清空
						}
					}
				}

				if (checkTranDatagram() < 0) //Set Hold Datagram
				{
					msleep(100); //每条命令延时
				}
				else
				{
					msleep(50);
					readChangedBankHoldReg();
					msleep(50);
				}
			}

			// Stack Data
			if (requestSlaveBAStack() < 0)
			{
				++iErrNum;
			}
			else
			{
				iErrNum = 0; // 分析正确清空
			}

			if (checkTranDatagram() < 0) //Set Hold Datagram
			{
				msleep(100); //每条命令延时
			}
			else
			{
				msleep(50);
				readChangedBankHoldReg();
				msleep(50);
			}
			
			if (m_bAcquSglDataEnable) //电池保持寄存器
			{
				if (processStackHoldReg() < 0)
				{
					++iErrNum;
				}
				else
				{
					iErrNum = 0; // 分析正确清空
				}

				if (checkTranDatagram() < 0) //Set Hold Datagram
				{
					msleep(100); //每条命令延时
				}
				else
				{
					msleep(50);
					readChangedBankHoldReg();
					msleep(50);
				}
			}

			// Process data
			for (int i = 0; i < m_pLstBatt->size(); ++i)
			{
				pBattBank = m_pLstBatt->at(i);

				if (pBattBank)
				{
					iIndexStep = 0;
					while (iIndexStep < BA_MODBUS_CMD_NUM)
					{
						iRetVal = m_pModbusFactory->prepareDatagram(iIndexStep, m_pDataBuf, pBattBank->uaModbusAddr); // >= 0 OK  -1 准备失败  -2 最后了

						if (iRetVal >= 0)
						{
							printSendInfo(iIndexStep, m_pDataBuf, iRetVal);

							if (iRetVal != m_pTcpClient->write(m_pDataBuf, iRetVal))
							{
								++iErrNum;
								emit addLog(RUN_LOG_FAILED, QString("Write data(%1) to BA(%2:%3) FAILED.").arg(getMsgFromIndexStep(iIndexStep)).arg(m_strIP).arg(m_usPort));
							}
							else
							{
								m_pTcpClient->flush();

								// receive data
								if (!m_pTcpClient->waitForReadyRead(1500)) //timeout
								{
									++iErrNum;
									emit addLog(RUN_LOG_FAILED, QString("Read data(%1) to BA(%2:%3) Timeout.").arg(getMsgFromIndexStep(iIndexStep)).arg(m_strIP).arg(m_usPort));
								}
								else
								{
									memset(m_pDataBuf, 0, SNED_BUFFER_LENGHT);
									iRetVal = m_pTcpClient->read(m_pDataBuf, SNED_BUFFER_LENGHT);

									if (iRetVal >= 0) //read OK
									{
										printReceInfo(iIndexStep, m_pDataBuf, iRetVal);

										iRetVal = m_pModbusFactory->analyDatagram(iIndexStep, m_pDataBuf, iRetVal, pBattBank);

										if (0 == iRetVal)
										{
											emit addLog(RUN_LOG_OK, QString("Analy Datagram:%1 OK.").arg(getMsgFromIndexStep(iIndexStep)));
										}
										else
										{
											emit addLog(RUN_LOG_FAILED, QString("Analy Datagram:%1 FAILED. Err Code:%2.").arg(getMsgFromIndexStep(iIndexStep)).arg(iRetVal));
										}
									}

									iErrNum = 0; // 分析正确清空
								}
							}
						}

						++iIndexStep;
						if (m_bAcquSglDataEnable) //采集单体
						{
							if (10 == iIndexStep/*Temp*/ || 18 == iIndexStep/*SOC*/ || 26 == iIndexStep/*Res*/ || 34 == iIndexStep/*Soh*/ || 43 == iIndexStep/*Last*/)
							{
								msleep(100); //每条命令延时

								// Stack Data
								if (requestSlaveBAStack() < 0)
								{
									++iErrNum;
								}
								else
								{
									iErrNum = 0; // 分析正确清空
								}
							}

							adjustIndexStep(iIndexStep);
						}
						else
						{
							if (1 == iIndexStep) //单体数据
							{
								iIndexStep = 41;
							}
						}

						if (iErrNum > 5) //断开,重新连接
						{
							m_pTcpClient->close();
							m_bTcpConnected = false;
							iErrNum = 0;

							emit addLog(RUN_LOG_FAILED, QString("BA(%1:%2) Disconnected FORCIBLY.").arg(m_strIP).arg(m_usPort));

							break;
						}

						if (checkTranDatagram() < 0) //Set Hold Datagram
						{
							msleep(100); //每条命令延时
						}
						else
						{
							msleep(50);
							readChangedBankHoldReg();
							msleep(50);
						}
					}

					// 电池组保持寄存器
					if (m_bAcquSglDataEnable) //电池保持寄存器
					{
						if (processBankHoldReg(pBattBank, i) < 0)
						{
							++iErrNum;
						}
						else
						{
							iErrNum = 0; //分析正确清空
						}

						if (checkTranDatagram() < 0) //Set Hold Datagram
						{
							msleep(100); //每条命令延时
						}
						else
						{
							msleep(50);
							readChangedBankHoldReg();
							msleep(50);
						}
					}

					if (!m_bTcpConnected)
					{
						break;
					}
				}

				msleep(200); //每组电池延时
			}
		}

		msleep(100);
	}
}

void CBA::printSendInfo(int iIndexStep, char* pSendBufData, int iLen)
{
	if (!m_bPrintBAMsg)
	{
		return;
	}

	QString strPrintInfo = "";
	QChar aFillChar = '0';

	for (int i = 0; i < iLen; ++i)
	{
		strPrintInfo += QString("%1 ").arg((uchar)*(pSendBufData + i), 2, 16, aFillChar);
	}

	strPrintInfo = strPrintInfo.toUpper();

	strPrintInfo =  "Send " + getMsgFromIndexStep(iIndexStep) + " Datagram:" + strPrintInfo;

	emit addLog(RUN_LOG_MESSAGE_BA, strPrintInfo);
}

void CBA::printReceInfo(int iIndexStep, char* pSendBufData, int iLen)
{
	if (!m_bPrintBAMsg)
	{
		return;
	}

	QString strPrintInfo = "";
	QChar aFillChar = '0';

	for (int i = 0; i < iLen; ++i)
	{
		strPrintInfo += QString("%1 ").arg((uchar)*(pSendBufData + i), 2, 16, aFillChar);
	}

	strPrintInfo = strPrintInfo.toUpper();

	strPrintInfo = "Rece " + getMsgFromIndexStep(iIndexStep) + " Datagram:" + strPrintInfo;

	emit addLog(RUN_LOG_MESSAGE_BA, strPrintInfo);
}

void CBA::setIPAndPort(const QString& strIP, ushort usPort)
{
	m_strIP = strIP; //BA IP
	m_usPort = usPort; //BA Port	
}

int CBA::addBattBank(uchar uaModbusAddr, uchar uaModbusAddrBg)
{
	if (getBattBankByMaddr(uaModbusAddr) || getBattBankByMaddrBg(uaModbusAddrBg, 0)) //存在
	{
		return -1;
	}

	CBattBank* pBatt = new CBattBank;
	memset(pBatt, 0, sizeof(CBattBank));

    // pBatt->usBCMUInput1 = 1; //默认为闭合
    // pBatt->usBankStatePCS = 0xbbbb; //默认为正常
    // pBatt->fBCMUBankTemp = -999; //默认环境温度
	for (int i = 0; i < MAX_BATT_NUM; ++i)
	{
		pBatt->fSglTemp[i] = -999; //默认单体温度
	}

	pBatt->uaModbusAddr = uaModbusAddr;
	pBatt->uaModbusAddrBg = uaModbusAddrBg;

	m_pLstBatt->append(pBatt);

	// Alarm param
	SAlarmParam* pAlarmParam = new SAlarmParam;
	memset(pAlarmParam, 0, sizeof(SAlarmParam));
	m_pLstSlaveParam->append(pAlarmParam);

	return 0;
}

CBattBank* CBA::getBattBankByMaddr(uchar uaModbusAddr)
{
	for (int i = 0; i < m_pLstBatt->size(); ++i)
	{
		CBattBank* pBatt = m_pLstBatt->at(i);

		if (pBatt)
		{
			if (uaModbusAddr == pBatt->uaModbusAddr) //find
			{
				return pBatt;
			}
		}
	}

	return 0;
}

CBattBank* CBA::getBattBankByMaddrBg(uchar uaModbusAddrBg, SAlarmParam** pAlarmParam)
{
	for (int i = 0; i < m_pLstBatt->size() && i < m_pLstSlaveParam->size(); ++i)
	{
		CBattBank* pBatt = m_pLstBatt->at(i);

		if (pBatt)
		{
			if (uaModbusAddrBg == pBatt->uaModbusAddrBg) //find
			{
				if (pAlarmParam)
				{
					*pAlarmParam = m_pLstSlaveParam->at(i);
				}
				
				return pBatt;
			}
		}
	}

	return 0;
}

CBattStack* CBA::getStack()
{
	return m_pBattStack;
}

QString CBA::getMsgFromIndexStep(int iIndexStep)
{
	QString strInfo = QString("[%1:%2] ").arg(m_strIP).arg(m_usPort);


	switch (iIndexStep)
	{
	case 0: // formDatagram(1/*读取告警状态*/, uaAddr, 2, 1, 49, pSendDataBuf); //离散输入寄存器 1 ~ 49
		strInfo += "Read Alarm State(StartReg:1 RegNum:52)";
		break;

	case 1: // formDatagram(8/*读取电池1~50 电压*/, uaAddr, 4, 1, 100, pSendDataBuf); //输入寄存器 1 ~ 99
		strInfo += "Read Single Vol[1~50](StartReg:1 RegNum:100)";
		break;
	case 2: // formDatagram(9/*读取电池51~100电压*/, uaAddr, 4, 101, 100, pSendDataBuf); //输入寄存器 101 ~ 199
		strInfo += "Read Single Vol[51~100](StartReg:101 RegNum:100)";
		break;
	case 3: // formDatagram(10/*读取电池101~150电压*/, uaAddr, 4, 201, 100, pSendDataBuf); //输入寄存器 201 ~ 299
		strInfo += "Read Single Vol[101~150](StartReg:201 RegNum:100)";
		break;
	case 4: // formDatagram(11/*读取电池151~200电压*/, uaAddr, 4, 301, 100, pSendDataBuf); //输入寄存器 301 ~ 399
		strInfo += "Read Single Vol[151~200](StartReg:301 RegNum:100)";
		break;
	case 5: // formDatagram(12/*读取电池201~250电压*/, uaAddr, 4, 401, 100, pSendDataBuf); //输入寄存器 401 ~ 499
		strInfo += "Read Single Vol[201~250](StartReg:401 RegNum:100)";
		break;
	case 6: // formDatagram(13/*读取电池251~300电压*/, uaAddr, 4, 501, 100, pSendDataBuf); //输入寄存器 501 ~ 599
		strInfo += "Read Single Vol[251~300](StartReg:501 RegNum:100)";
		break;
	case 7: // formDatagram(14/*读取电池301~350电压*/, uaAddr, 4, 601, 100, pSendDataBuf); //输入寄存器 601 ~ 699
		strInfo += "Read Single Vol[301~350](StartReg:601 RegNum:100)";
		break;
	case 8: // formDatagram(15/*读取电池350~400电压*/, uaAddr, 4, 701, 100, pSendDataBuf); //输入寄存器 701 ~ 799 
		strInfo += "Read Single Vol[350~400](StartReg:701 RegNum:100)";
		break;

	case 9: // formDatagram(16/*读取电池1~50 温度*/, uaAddr, 4, 801, 100, pSendDataBuf); //输入寄存器 801 ~ 899
		strInfo += "Read Single Temp[1~50](StartReg:801 RegNum:100)";
		break;
	case 10: // formDatagram(17/*读取电池51~100温度*/, uaAddr, 4, 901, 100, pSendDataBuf); //输入寄存器 901 ~ 999
		strInfo += "Read Single Temp[51~100](StartReg:901 RegNum:100)";
		break;
	case 11: // formDatagram(18/*读取电池101~150温度*/, uaAddr, 4, 1001, 100, pSendDataBuf); //输入寄存器 1001 ~ 1099
		strInfo += "Read Single Temp[101~150](StartReg:1001 RegNum:100)";
		break;
	case 12: // formDatagram(19/*读取电池151~200温度*/, uaAddr, 4, 1101, 100, pSendDataBuf); //输入寄存器 1101 ~ 1199
		strInfo += "Read Single Temp[151~200](StartReg:1101 RegNum:100)";
		break;
	case 13: // formDatagram(20/*读取电池201~250温度*/, uaAddr, 4, 1201, 100, pSendDataBuf); //输入寄存器 1201 ~ 1299
		strInfo += "Read Single Temp[201~250](StartReg:1201 RegNum:100)";
		break;
	case 14: // formDatagram(21/*读取电池251~300温度*/, uaAddr, 4, 1301, 100, pSendDataBuf); //输入寄存器 1301 ~ 1399
		strInfo += "Read Single Temp[251~300](StartReg:1301 RegNum:100)";
		break;
	case 15: // formDatagram(22/*读取电池301~350温度*/, uaAddr, 4, 1401, 100, pSendDataBuf); //输入寄存器 1401 ~ 1499
		strInfo += "Read Single Temp[301~350](StartReg:1401 RegNum:100)";
		break;
	case 16: // formDatagram(23/*读取电池350~400温度*/, uaAddr, 4, 1501, 100, pSendDataBuf); //输入寄存器 1501 ~ 1599
		strInfo += "Read Single Temp[350~400](StartReg:1501 RegNum:100)";
		break;

	case 17: // formDatagram(24/*读取电池1~50 Soc*/, uaAddr, 4, 1601, 100, pSendDataBuf); //输入寄存器 1601 ~ 1699
		strInfo += "Read Single Soc[1~50](StartReg:1601 RegNum:100)";
		break;
	case 18: // formDatagram(25/*读取电池51~100Soc*/, uaAddr, 4, 1701, 100, pSendDataBuf); //输入寄存器 1701 ~ 1799
		strInfo += "Read Single Soc[51~100](StartReg:1701 RegNum:100)";
		break;
	case 19: // formDatagram(26/*读取电池101~150Soc*/, uaAddr, 4, 1801, 100, pSendDataBuf); //输入寄存器 1801 ~ 1899
		strInfo += "Read Single Soc[101~150](StartReg:1801 RegNum:100)";
		break;
	case 20: // formDatagram(27/*读取电池151~200Soc*/, uaAddr, 4, 1901, 100, pSendDataBuf); //输入寄存器 1901 ~ 1999
		strInfo += "Read Single Soc[151~200](StartReg:1901 RegNum:100)";
		break;
	case 21: // formDatagram(28/*读取电池201~250Soc*/, uaAddr, 4, 2001, 100, pSendDataBuf); //输入寄存器 2001 ~ 2099
		strInfo += "Read Single Soc[201~250](StartReg:2001 RegNum:100)";
		break;
	case 22: // formDatagram(29/*读取电池251~300Soc*/, uaAddr, 4, 2101, 100, pSendDataBuf); //输入寄存器 2101 ~ 2199
		strInfo += "Read Single Soc[251~300](StartReg:2101 RegNum:100)";
		break;
	case 23: // formDatagram(30/*读取电池301~350Soc*/, uaAddr, 4, 2201, 100, pSendDataBuf); //输入寄存器 2201 ~ 2299
		strInfo += "Read Single Soc[301~350](StartReg:2201 RegNum:100)";
		break;
	case 24: // formDatagram(31/*读取电池350~400Soc*/, uaAddr, 4, 2301, 100, pSendDataBuf); //输入寄存器 2301 ~ 2399
		strInfo += "Read Single Soc[350~400](StartReg:2301 RegNum:100)";
		break;

	case 25: // formDatagram(32/*读取电池1~50 内阻*/, uaAddr, 4, 2401, 100, pSendDataBuf); //输入寄存器 2401 ~ 2499
		strInfo += "Read Single Res[1~50](StartReg:2401 RegNum:100)";
		break;
	case 26: // formDatagram(33/*读取电池51~100内阻*/, uaAddr, 4, 2501, 100, pSendDataBuf); //输入寄存器 2501 ~ 2599
		strInfo += "Read Single Res[51~100](StartReg:2501 RegNum:100)";
		break;
	case 27: // formDatagram(34/*读取电池101~150内阻*/, uaAddr, 4, 2601, 100, pSendDataBuf); //输入寄存器 2601 ~ 2699
		strInfo += "Read Single Res[101~150](StartReg:2601 RegNum:100)";
		break;
	case 28: // formDatagram(35/*读取电池151~200内阻*/, uaAddr, 4, 2701, 100, pSendDataBuf); //输入寄存器 2701 ~ 2799
		strInfo += "Read Single Res[151~200](StartReg:2701 RegNum:100)";
		break;
	case 29: // formDatagram(36/*读取电池201~250内阻*/, uaAddr, 4, 2801, 100, pSendDataBuf); //输入寄存器 2801 ~ 2899
		strInfo += "Read Single Res[201~250](StartReg:2801 RegNum:100)";
		break;
	case 30: // formDatagram(37/*读取电池251~300内阻*/, uaAddr, 4, 2901, 100, pSendDataBuf); //输入寄存器 2901 ~ 2999
		strInfo += "Read Single Res[251~300](StartReg:2901 RegNum:100)";
		break;
	case 31: // formDatagram(38/*读取电池301~350内阻*/, uaAddr, 4, 3001, 100, pSendDataBuf); //输入寄存器 3001 ~ 3099
		strInfo += "Read Single Res[301~350](StartReg:3001 RegNum:100)";
		break;
	case 32: // formDatagram(39/*读取电池350~400内阻*/, uaAddr, 4, 3101, 100, pSendDataBuf); //输入寄存器 3101 ~ 3199
		strInfo += "Read Single Res[350~400](StartReg:3101 RegNum:100)";
		break;

	case 33: // formDatagram(40/*读取电池1~50 Soh*/, uaAddr, 4, 3201, 100, pSendDataBuf); //输入寄存器 3201 ~ 3299
		strInfo += "Read Single Soh[1~50](StartReg:3201 RegNum:100)";
		break;
	case 34: // formDatagram(41/*读取电池51~100Soh*/, uaAddr, 4, 3301, 100, pSendDataBuf); //输入寄存器 3301 ~ 3399
		strInfo += "Read Single Soh[51~100](StartReg:3301 RegNum:100)";
		break;
	case 35: // formDatagram(42/*读取电池101~150Soh*/, uaAddr, 4, 3401, 100, pSendDataBuf); //输入寄存器 3401 ~ 3499
		strInfo += "Read Single Soh[101~150](StartReg:3401 RegNum:100)";
		break;
	case 36: // formDatagram(43/*读取电池151~200Soh*/, uaAddr, 4, 3501, 100, pSendDataBuf); //输入寄存器 3501 ~ 3599
		strInfo += "Read Single Soh[151~200](StartReg:3501 RegNum:100)";
		break;
	case 37: // formDatagram(44/*读取电池201~250Soh*/, uaAddr, 4, 3601, 100, pSendDataBuf); //输入寄存器 3601 ~ 3699
		strInfo += "Read Single Soh[201~250](StartReg:3601 RegNum:100)";
		break;
	case 38: // formDatagram(45/*读取电池251~300Soh*/, uaAddr, 4, 3701, 100, pSendDataBuf); //输入寄存器 3701 ~ 3799
		strInfo += "Read Single Soh[251~300](StartReg:3701 RegNum:100)";
		break;
	case 39: // formDatagram(46/*读取电池301~350Soh*/, uaAddr, 4, 3801, 100, pSendDataBuf); //输入寄存器 3801 ~ 3899
		strInfo += "Read Single Soh[301~350](StartReg:3801 RegNum:100)";
		break;
	case 40: // formDatagram(47/*读取电池350~400Soh*/, uaAddr, 4, 3901, 100, pSendDataBuf); //输入寄存器 3901 ~ 3999
		strInfo += "Read Single Soh[350~400](StartReg:3901 RegNum:100)";
		break;

	case 41: // formDatagram(48/*读取其他浮点数*/, uaAddr, 4, 4001, 56, pSendDataBuf); //输入寄存器 4001 ~ 4055
		strInfo += "Read Other FLOAT Value(StartReg:4001 RegNum:56)";
		break;

	case 42: // formDatagram(49/*读取其他短整形数*/, uaAddr, 4, 5001, 16, pSendDataBuf); //输入寄存器 5001 ~ 5025
		strInfo += "Read Other INT Value(StartReg:5001 RegNum:25)";
		break;

	case 200: // 通用输入寄存器
		strInfo += "Read Common Input Reg(StartReg:1 RegNum:100)";
		break;
	case 201: // 从BA电池堆数据
		strInfo += "Slave BA Stack(StartReg:1 RegNum:87)";
		break;
	case 202: // 从BA电池堆保持寄存器
		strInfo += "Stack Hold Register(StartReg:1 RegNum:8)";
		break;
	case 203: // 从BA电池组保持寄存器
		strInfo += "Bank Hold Register(StartReg:1 RegNum:44)";
		break;

	case 301: // 设置电池堆保持寄存器
		strInfo += "Set Stack Hold Register(StartReg:1 RegNum:1)";
		break;
	case 302: // 设置预警参数
		strInfo += "Set Warn Param(StartReg:1 RegNum:12)";
		break;
	case 303: // 设置告警参数
		strInfo += "Set Alarm Param(StartReg:13 RegNum:12)";
		break;
	case 304: // 设置保护参数
		strInfo += "Set Prot Param(StartReg:25 RegNum:12)";
		break;
	case 305: // 设置调整步长
		strInfo += "Set Step Param(StartReg:37 RegNum:8)";
		break;
	default:
		strInfo = "";
		break;
	}

	return strInfo;
}

QString CBA::getIP()
{
	return m_strIP;
}

ushort CBA::getPort()
{
	return m_usPort;
}

int CBA::getBattBankSize()
{
	return m_pLstBatt->size();
}

CBattBank* CBA::getBattBankByIndex(int iIndex)
{
	if (iIndex < m_pLstBatt->size() && iIndex >= 0)
	{
		return m_pLstBatt->at(iIndex);
	}

	return 0;
}

void CBA::enableAcquComInputReg(int iBAIndex)
{
	m_bAcquComInputRegEnable = true;
	m_iBAIndex = iBAIndex + 100;
}

void CBA::setBAIndex(int iBAIndex)
{
	m_iBAIndex = iBAIndex + 100;
}

void CBA::enableAcquSglData(int iCellNum, int iTempNum)
{
	m_iCellNum = iCellNum;
	m_iTempNum = iTempNum;

	m_bAcquSglDataEnable = true;
}

bool CBA::isEnableAcquComInputReg()
{
	return m_bAcquComInputRegEnable;
}

int CBA::getBAIndex()
{
	return m_iBAIndex;
}

quint16* CBA::getComInputReg()
{
	return m_usComInputRegVal;
}

int CBA::getRegVal(quint16 usModbusAddr, quint16 usRegAddr, quint16& usVal)
{
	if (usModbusAddr == (quint16)m_iBAIndex && usRegAddr <= 100 && usRegAddr > 0)
	{
		usVal = m_usComInputRegVal[usRegAddr - 1];

		return 0;
	}

	return -1;
}

bool CBA::getBAConnectedState()
{
	return m_bBAConnected;
}

void CBA::enablePrintBAMsg(bool bPrint)
{
	m_bPrintBAMsg = bPrint;
}

// -1 - Prepare datagram FAILED
// -2 - Write datagram FAILED
// -3 - Receive datagram FAILED
// -4 - Parse datagram FAILED
// -5 - Read datagram FAILED
//  0 - OK
int CBA::requestSlaveBAStack()
{
	// some variables
	int iRetVal = -999;
	quint16 usTemp = 0;

	iRetVal = m_pModbusFactory->prepareDatagram(201, m_pDataBuf, 1); // >= 0 OK  -1 准备失败  -2 最后了

	if (iRetVal >= 0)
	{
		// 协议标识 C0C0 0 - 正常   C1C1 1 - 联动跳机
		if (1 == m_iLinkageStrategy)
		{
            // if (0 == m_pBattStack->usLinkageTripCtrl)
            // {
            // 	usTemp = 0xC0C0;
            // }
            // else if (1 == m_pBattStack->usLinkageTripCtrl)
            // {
            // 	usTemp = 0xC1C1;
            // }
            // else if (2 == m_pBattStack->usLinkageTripCtrl)
            // {
            // 	usTemp = 0xC2C2;
            // }
            // else if (3 == m_pBattStack->usLinkageTripCtrl)
            // {
            // 	usTemp = 0xC3C3;
            // }
            // else
            // {
            // 	usTemp = 0xC0C0;
            // }

			m_pModbusFactory->addParam2Buffer(m_pDataBuf + 2, usTemp); // 协议标识
		}

		printSendInfo(201, m_pDataBuf, iRetVal);

		if (iRetVal != m_pTcpClient->write(m_pDataBuf, iRetVal))
		{
			emit addLog(RUN_LOG_FAILED, QString("Write data(%1) to BA(%2:%3) FAILED.").arg(getMsgFromIndexStep(201)).arg(m_strIP).arg(m_usPort));
			iRetVal = -2;
		}
		else
		{
			m_pTcpClient->flush();

			// receive data
			if (!m_pTcpClient->waitForReadyRead(1500)) //timeout
			{
				emit addLog(RUN_LOG_FAILED, QString("Read data(%1) to BA(%2:%3) Timeout.").arg(getMsgFromIndexStep(201)).arg(m_strIP).arg(m_usPort));
				iRetVal = -3;
			}
			else
			{
				memset(m_pDataBuf, 0, SNED_BUFFER_LENGHT);
				iRetVal = m_pTcpClient->read(m_pDataBuf, SNED_BUFFER_LENGHT);

				if (iRetVal >= 0) //read OK
				{
					printReceInfo(201, m_pDataBuf, iRetVal);

					iRetVal = m_pModbusFactory->analyStackDatagram(m_pDataBuf, iRetVal, m_pBattStack);

					if (0 == iRetVal)
					{
						emit addLog(RUN_LOG_OK, QString("Analy Datagram:%1 OK.").arg(getMsgFromIndexStep(201)));
						iRetVal = 0;
					}
					else
					{
						emit addLog(RUN_LOG_FAILED, QString("Analy Datagram:%1 FAILED. Err Code:%2.").arg(getMsgFromIndexStep(201)).arg(iRetVal));
						iRetVal = -4;
					}
				}
				else
				{
					iRetVal = -5;
				}
			}
		}
	}
	else
	{
		iRetVal = -1;
	}

	return iRetVal;
}

// -1 - Prepare datagram FAILED
// -2 - Write datagram FAILED
// -3 - Receive datagram FAILED
// -4 - Parse datagram FAILED
// -5 - Read datagram FAILED
// -6 - Set hold reg FAILED
//  0 - OK
int CBA::processStackHoldReg()
{
	// some variables
	int iRetVal = -999;

	iRetVal = m_pModbusFactory->prepareDatagram(202, m_pDataBuf, 1); // >= 0 OK  -1 准备失败  -2 最后了

	if (iRetVal >= 0)
	{
		printSendInfo(202, m_pDataBuf, iRetVal);

		if (iRetVal != m_pTcpClient->write(m_pDataBuf, iRetVal))
		{
			emit addLog(RUN_LOG_FAILED, QString("Write data(%1) to BA(%2:%3) FAILED.").arg(getMsgFromIndexStep(202)).arg(m_strIP).arg(m_usPort));
			iRetVal = -2;
		}
		else
		{
			m_pTcpClient->flush();

			// receive data
			if (!m_pTcpClient->waitForReadyRead(1500)) //timeout
			{
				emit addLog(RUN_LOG_FAILED, QString("Read data(%1) to BA(%2:%3) Timeout.").arg(getMsgFromIndexStep(202)).arg(m_strIP).arg(m_usPort));
				iRetVal = -3;
			}
			else
			{
				memset(m_pDataBuf, 0, SNED_BUFFER_LENGHT);
				iRetVal = m_pTcpClient->read(m_pDataBuf, SNED_BUFFER_LENGHT);

				if (iRetVal >= 0) //read OK
				{
					printReceInfo(202, m_pDataBuf, iRetVal);

					iRetVal = m_pModbusFactory->analyStackHoldDatagram(m_pDataBuf, iRetVal, m_pBattStack);

					if (0 == iRetVal)
					{
						emit addLog(RUN_LOG_OK, QString("Analy Datagram:%1 OK.").arg(getMsgFromIndexStep(202)));
						iRetVal = 0;
					}
					else
					{
						emit addLog(RUN_LOG_FAILED, QString("Analy Datagram:%1 FAILED. Err Code:%2.").arg(getMsgFromIndexStep(202)).arg(iRetVal));
						iRetVal = -4;
					}
				}
				else
				{
					iRetVal = -5;
				}
			}
		}
	}
	else
	{
		iRetVal = -1;
	}

	return iRetVal;
}

// -1 - Prepare datagram FAILED
// -2 - Write datagram FAILED
// -3 - Receive datagram FAILED
// -4 - Parse datagram FAILED
// -5 - Read datagram FAILED
// -6 - Param error
//  0 - OK
int CBA::processBankHoldReg(CBattBank* pBattBank, int iIndex)
{
	if (iIndex < 0 || iIndex >= m_pLstSlaveParam->size() || !pBattBank)
	{
		return -6;
	}

	// some variables
	int iRetVal = -999;
	SAlarmParam* alarmParam = m_pLstSlaveParam->at(iIndex);

	if (alarmParam)
	{
		iRetVal = m_pModbusFactory->prepareDatagram(203, m_pDataBuf, pBattBank->uaModbusAddr); // >= 0 OK  -1 准备失败  -2 最后了

		if (iRetVal >= 0)
		{
			printSendInfo(203, m_pDataBuf, iRetVal);

			if (iRetVal != m_pTcpClient->write(m_pDataBuf, iRetVal))
			{
				emit addLog(RUN_LOG_FAILED, QString("Write data(%1) to BA(%2:%3) FAILED.").arg(getMsgFromIndexStep(203)).arg(m_strIP).arg(m_usPort));
				iRetVal = -2;
			}
			else
			{
				m_pTcpClient->flush();

				// receive data
				if (!m_pTcpClient->waitForReadyRead(1500)) //timeout
				{
					emit addLog(RUN_LOG_FAILED, QString("Read data(%1) to BA(%2:%3) Timeout.").arg(getMsgFromIndexStep(203)).arg(m_strIP).arg(m_usPort));
					iRetVal = -3;
				}
				else
				{
					memset(m_pDataBuf, 0, SNED_BUFFER_LENGHT);
					iRetVal = m_pTcpClient->read(m_pDataBuf, SNED_BUFFER_LENGHT);

					if (iRetVal >= 0) //read OK
					{
						printReceInfo(203, m_pDataBuf, iRetVal);

                        // iRetVal = m_pModbusFactory->analyBankHoldDatagram(m_pDataBuf, iRetVal, pBattBank, alarmParam);

						if (0 == iRetVal)
						{
							emit addLog(RUN_LOG_OK, QString("Analy Datagram:%1 OK.").arg(getMsgFromIndexStep(203)));
							iRetVal = 0;
						}
						else
						{
							emit addLog(RUN_LOG_FAILED, QString("Analy Datagram:%1 FAILED. Err Code:%2.").arg(getMsgFromIndexStep(203)).arg(iRetVal));
							iRetVal = -4;
						}
					}
					else
					{
						iRetVal = -5;
					}
				}
			}
		}
		else
		{
			iRetVal = -1;
		}
	}
	else
	{
		iRetVal = -6;
	}

	return iRetVal;
}

// -1 - Prepare datagram FAILED
// -2 - Write datagram FAILED
// -3 - Receive datagram FAILED
// -4 - Parse datagram FAILED
// -5 - Read datagram FAILED
//  0 - OK
//int CBA::processSetHoldReg(int iSetHoldRegStep, CBattBank* pBattBank, SAlarmParam* pAlarmParam)
//{
//	// some variables
//	int iRetVal = -999;
//
//	iRetVal = m_pModbusFactory->prepareSetHoldDatagram(iSetHoldRegStep, m_pBattStackMaster, pBattBank, pAlarmParam, m_pDataBuf); // >= 0 OK  -1 准备失败  -2 最后了	
//
//	if (iRetVal >= 0)
//	{
//		printSendInfo(iSetHoldRegStep, m_pDataBuf, iRetVal);
//
//		if (iRetVal != m_pTcpClient->write(m_pDataBuf, iRetVal))
//		{
//			emit addLog(RUN_LOG_FAILED, QString("Write data(%1) to BA(%2:%3) FAILED.").arg(getMsgFromIndexStep(iSetHoldRegStep)).arg(m_strIP).arg(m_usPort));
//			iRetVal = -2;
//		}
//		else
//		{
//			m_pTcpClient->flush();
//
//			// receive data
//			if (!m_pTcpClient->waitForReadyRead(1500)) //timeout
//			{
//				emit addLog(RUN_LOG_FAILED, QString("Read data(%1) to BA(%2:%3) Timeout.").arg(getMsgFromIndexStep(iSetHoldRegStep)).arg(m_strIP).arg(m_usPort));
//				iRetVal = -3;
//			}
//			else
//			{
//				memset(m_pDataBuf, 0, SNED_BUFFER_LENGHT);
//				iRetVal = m_pTcpClient->read(m_pDataBuf, SNED_BUFFER_LENGHT);
//
//				if (iRetVal >= 0) //read OK
//				{
//					printReceInfo(iSetHoldRegStep, m_pDataBuf, iRetVal);
//
//					iRetVal = m_pModbusFactory->analySetHoldReturnDatagram(m_pDataBuf, iRetVal);
//
//					if (0 == iRetVal)
//					{
//						iRetVal = 0;
//					}
//					else
//					{
//						iRetVal = -4;
//					}
//				}
//				else
//				{
//					iRetVal = -5;
//				}
//			}
//		}
//	}
//	else
//	{
//		iRetVal = -1;
//	}
//
//	return iRetVal;
//}

void CBA::adjustIndexStep(int& iIndexStep)
{
	if (iIndexStep > 1 && iIndexStep <= 8) //单体电压
	{
		if (m_iCellNum > 0)
		{
			if ((iIndexStep - 1) * 50 >= m_iCellNum)
			{
				iIndexStep = 9; //跳到温度
			}
		}
	}
	else if (iIndexStep > 9 && iIndexStep <= 16) //单体温度
	{
		if (m_iTempNum > 0)
		{
			if ((iIndexStep - 9) * 50 >= m_iTempNum)
			{
				iIndexStep = 17; //跳到SOC
			}
		}
	}
	else if (iIndexStep > 17 && iIndexStep <= 24) //单体Soc
	{
		if (m_iCellNum > 0)
		{
			if ((iIndexStep - 17) * 50 >= m_iCellNum)
			{
				iIndexStep = 25; //跳到Res
			}
		}
	}
	else if (iIndexStep > 25 && iIndexStep <= 32) //单体Res
	{
		if (m_iCellNum > 0)
		{
			if ((iIndexStep - 25) * 50 >= m_iCellNum)
			{
				iIndexStep = 33; //跳到Soh
			}
		}
	}
	else if (iIndexStep > 33 && iIndexStep <= 40) //单体Soh
	{
		if (m_iCellNum > 0)
		{
			if ((iIndexStep - 33) * 50 >= m_iCellNum)
			{
				iIndexStep = 41; //跳到 浮点
			}
		}
	}
}

//  0 - OK
// -1 - 参数错误
// -2 - 不能找到后台对应的Modbus地址
// -3 - 超时
int CBA::tranSetHoldReg2Slave(char* pDataBuf, int iLen, uchar uaAddrBg)
{
	if (!pDataBuf || iLen < 6 || uaAddrBg < 2)
	{
		return -1;
	}

	// some variables
	CBattBank* pBatt = 0;
	int iRetVal = -999;
	for (int i = 0; i < m_pLstBatt->size(); ++i)
	{
		pBatt = m_pLstBatt->at(i);

		if (pBatt)
		{
			if (uaAddrBg == pBatt->uaModbusAddrBg) //find
			{
				break;
			}
			else
			{
				pBatt = 0;
			}
		}
	}

	if (pBatt)
	{
		m_pTranDataBuf = pDataBuf;
		m_iTranDataLen = iLen;

		// Modify modbus address
		m_uaAddrBg = uaAddrBg;
		*(pDataBuf + 6) = pBatt->uaModbusAddr;

		// Clear
		iLen = m_pSemaphore->available();
		if (iLen > 0)
		{
			m_pSemaphore->tryAcquire(iLen);
		}

		m_pSemaphore->release(); // 1

		if (m_pSemaphore->tryAcquire(2, 2000))
		{
			iRetVal = m_iTranDataLen;
			m_iTranDataLen = -1;
		}
		else
		{
			m_iTranDataLen = -1;
			iRetVal = -3;
		}

		// Clear
		iLen = m_pSemaphore->available();
		if (iLen > 0)
		{
			m_pSemaphore->tryAcquire(iLen);
		}
	}
	else
	{
		iRetVal = -2;
	}

	return iRetVal;
}

// -1 - 不用设置
// -2 - 转发不正常
// -3 - 超时
//  0 - 正确
int CBA::checkTranDatagram()
{
	int iRetVal = -1;
	if (m_iTranDataLen > 0 && m_pSemaphore->available() > 0)
	{
		if (m_iTranDataLen != m_pTcpClient->write(m_pTranDataBuf, m_iTranDataLen))
		{
			m_iTranDataLen = -1;

			iRetVal = -2;
		}
		else
		{
			m_pTcpClient->flush();

			// receive data
			if (!m_pTcpClient->waitForReadyRead(1000)) //timeout
			{
				m_iTranDataLen = -2; // time out

				iRetVal = -3;
			}
			else
			{
				memset(m_pTranDataBuf, 0, SNED_BUFFER_LENGHT);
				m_iTranDataLen = m_pTcpClient->read(m_pTranDataBuf, SNED_BUFFER_LENGHT);

				if (m_iTranDataLen > 6)
				{
					*(m_pTranDataBuf + 6) = m_uaAddrBg;
				}

				iRetVal = 0;
			}
		}

		m_pSemaphore->release();
	}

	return iRetVal;
}

void CBA::readChangedBankHoldReg()
{
	for (int i = 0; i < m_pLstBatt->size(); ++i)
	{
		CBattBank* pBatt = m_pLstBatt->at(i);

		if (pBatt)
		{
			if (m_uaAddrBg == pBatt->uaModbusAddrBg) //find
			{
				processBankHoldReg(pBatt, i);

				break;
			}
		}
	}
}

// // bLastLinkageTrip - 需要联动跳机
// // bLinkageTrip     - 状态返回
// // usLinkageTripState; 从BA->主BA      85          0 - 正常  1 - 触发联动跳机 2 - 联动跳机恢复(前提需要Ctrl状态为2) 维持状态
// // usLinkageTripCtrl; 主BA->从BA      86          0 - 正常  1 - 联动跳机     2 - 不接受控制 由State = 1 转来  3 - 恢复接受控制 由State = 2 转来
// void CBA::setLinkageTrip(bool bLastLinkageTrip, bool& bLinkageTrip)
// {
// 	if (1 == m_pBattStack->usLinkageTripState)
// 	{
// 		m_pBattStack->usLinkageTripCtrl = 2;
// 		bLinkageTrip = true;
// 	}
// 	else if (0 == m_pBattStack->usLinkageTripState)
// 	{
// 		if (bLastLinkageTrip) //需要跳机
// 		{
// 			m_pBattStack->usLinkageTripCtrl = 1;
// 		}
// 		else
// 		{
// 			m_pBattStack->usLinkageTripCtrl = 0;
// 		}
// 	}
// 	else if (2 == m_pBattStack->usLinkageTripState)
// 	{
// 		if (bLastLinkageTrip) //需要跳机
// 		{
// 			m_pBattStack->usLinkageTripCtrl = 1;
// 		}
// 		else
// 		{
// 			m_pBattStack->usLinkageTripCtrl = 3;
// 		}
// 	}
// 	else
// 	{
// 		m_pBattStack->usLinkageTripCtrl = 0;
// 	}
// }

void CBA::setLinkageStrategy(int iLinkageStrategy)
{
	m_iLinkageStrategy = iLinkageStrategy;
}
